﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.DirectX.AudioVideoPlayback;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Windows.Threading;
using SoundServant.Controls;

namespace SoundServant
{
    partial class MainWindow : Window
    {
        Burner burner;
        Recorder recorder;
        Congregation congregation;
        Sharing sharing;

        RecorderControl recorderControl;
        BrowserControl browserControl;
        BurnerControl burnerControl;
        ConfigControl configControl;
        SharingControl skypeControl = null;
        LogsControl logsControl;
        ToolsControl toolsControl;
        EditListenersControl editListenersControl;

        Controls.NavTab selectedNavTab;


        private delegate void ProgressInvokeHandler(int percent, string message);
        private delegate void VoidInvokeHandler();

        internal bool IsCloseable
        {
            get
            {
                if (burner.Queue.Count > 0 || burner.CurrentCD != null || burner.Status != BurnerStatus.Ready || recorder.RecorderState == RecorderStates.Recording || recorder.RecorderState == RecorderStates.Starting || recorder.SongState == SongStates.Playing || recorder.MusicState != MusicStates.Ready)
                    return false;
                else
                    return true;
            }
        }

        internal string IsntCloseableReason
        {
            get
            {
                if (!IsCloseable)
                {
                    string message = "";
                    if (burner.Queue.Count > 0)
                    {
                        message += "\r\nThere are " + burner.Queue.Count + " CDs in the Burner Queue";
                    }
                    if (burner.Status != BurnerStatus.Ready)
                    {
                        message += "\r\nThere is a cd currently burning";
                    }
                    if (recorder.RecorderState == RecorderStates.Recording || recorder.RecorderState == RecorderStates.Starting)
                    {
                        message += "\r\nYou are still recording";
                    }
                    if (recorder.SongState == SongStates.Playing)
                    {
                        message += "\r\nThere is a song playing";
                    }
                    if (recorder.MusicState != MusicStates.Ready)
                    {
                        message += "\r\nWelcome Music is playing";
                    }
                    if (message.Length > 0) message = message.Substring(2);
                    return message;
                }
                else
                    return "";
            }

        }

        public MainWindow()
        {
            InitializeComponent();

            try
            {
                SqlConnection connection = SS.Connection();
                SqlCommand command = new SqlCommand("SELECT COUNT(*) AS Row_Count FROM congregations", connection);
                int count = (int)command.ExecuteScalar();

                // Check to see how many congregations are in the database and take the appropriate action
                if (count == 1)
                {
                    command = new SqlCommand("SELECT congId FROM congregations", connection);
                    congregation = new Congregation((int)command.ExecuteScalar());
                }
                else
                {
                    LoadWindow loadWindow = new LoadWindow();
                    congregation = loadWindow.LoadCongDialog();
                }
                connection.Close();
                connection.Dispose();

                SS.FullScreenModeChanged += new SS.FullScreenModeChangedDelegate(SS_FullScreenModeChanged);

                Initialize();
            }
            catch (Exception e)
            {
                SSMessageBox.Show(e.ToString());
                this.Closing -= Window_Closing;
                this.Close();
            }
        }

        void SS_FullScreenModeChanged(bool fullScreenModeEnabled)
        {
            if (fullScreenModeEnabled)
            {
                this.WindowStyle = WindowStyle.None;
                this.WindowState = WindowState.Maximized;
            }
            else
            {
                this.WindowState = WindowState.Normal;
                this.WindowStyle = WindowStyle.SingleBorderWindow;
            }
        }

        public void Initialize()
        {
            // Run Sound Servant main initialiation method

            if (SS.FullScreenMode)
            {
                this.WindowStyle = WindowStyle.None;
                this.WindowState = WindowState.Maximized;
            }
            if (Options.Default.TouchScreenMode)
            {
                this.Cursor = Cursors.None;
            }

            // If re-initializing Sound Servant, this will check to see if any ot the tabs are already selected
            if (selectedNavTab != null)
            {
                selectedNavTab.Unselect();
                selectedNavTab = null;
            }

            // Setup basics
            CongregationLabel.Content = congregation.Name;
            SoundServantInfoLabel.Content = "Sound Servant " + SS.Version() + " " + SS.BuildDate();
            SS.TenthOfASecondTimer.Tick += new EventHandler(Time);

            // Create and initialize Sound Servant core classes
            recorder = new Recorder();
            recorder.Initialize(congregation);
            burner = new Burner();

            // sharing must be setup first.
            sharing = null;
            SharingNavTab.TabPage = null;
            EditListenersNavTab.TabPage = null;
            if (Options.Default.SkypeEnabled && congregation.SkypeEnabled)
            {
                try
                {
                    sharing = new Sharing(congregation, recorder);
                    sharing.Initialize();
                    skypeControl = new SharingControl(sharing);
                    SharingNavTab.TabPage = skypeControl;
                    editListenersControl = new EditListenersControl(congregation, sharing);
                    EditListenersNavTab.TabPage = editListenersControl;

                    SharingNavTab.Visibility = Visibility.Visible;
                    EditListenersNavTab.Visibility = Visibility.Visible;
                }
                catch (Exception e)
                {
                    Logs.Error("Skype", "Error trying to initialize skype", e.ToString());
                }
            }
            else
            {
                SharingNavTab.Visibility = Visibility.Collapsed;
                EditListenersNavTab.Visibility = Visibility.Collapsed;
            }

            // Setup Nav Tabs
            recorderControl = new RecorderControl(recorder, burner);
            RecorderNavTab.TabPage = recorderControl;
            browserControl = new BrowserControl(congregation, recorder, burner);
            BrowserNavTab.TabPage = browserControl;
            burnerControl = new BurnerControl(burner);
            BurnerNavTab.TabPage = burnerControl;
            configControl = new ConfigControl(recorder, burner, congregation, sharing, this);
            ConfigNavTab.TabPage = configControl;
            logsControl = new LogsControl(sharing);
            LogsNavTab.TabPage = logsControl;
            toolsControl = new ToolsControl(recorder, burner, congregation, sharing, this);
            ToolsNavTab.TabPage = toolsControl;

            // Select Recorder Nav Tab
            RecorderNavTab.Select();
            selectedNavTab = RecorderNavTab;
            TabHolder.Child = recorderControl;

            // Run Sound Servant Clean method
            SS.Clean();

            // Setup status bar Updates
            BurnerStatusLabel.Content = "ready";
            BurnerProgressLabel.Content = "0/0 000%";
            burner.Progress += new Burner.ProgressEventHandler(burner_Progress);
            burner.Starting += new Burner.VoidEventHandler(burner_Starting);
            burner.WaitingForCorrectMedia += new Burner.VoidEventHandler(burner_WaitingForCorrectMedia);
            burner.Finished += new Burner.FinishedEventHandler(burner_Finished);
            burner.Finishing += new Burner.VoidEventHandler(burner_Finishing);
            burner.Ready += new Burner.VoidEventHandler(burner_Ready);

            RecorderTimerLabel.Content = "0/0 0:00:00";
            RecorderStatusLabel.Content = "ready";
            recorder.RecorderStarted += new Recorder.VoidEventHandler(recorder_RecorderStarted);
            recorder.RecorderFinished += new Recorder.VoidEventHandler(recorder_RecorderFinished);
            recorder.RecorderStarting += new Recorder.VoidEventHandler(recorder_RecorderStarting);
            recorder.RecorderPaused += new Recorder.VoidEventHandler(recorder_RecorderPaused);
            recorder.RecorderUnpaused += new Recorder.VoidEventHandler(recorder_RecorderUnpaused);

            if (sharing != null)
            {
                SharingTimerLabel.Content = "0 0:00:00";
                SharingStatusLabel.Content = "ready";
                SharingStatusBorder.Visibility = Visibility.Visible;
                sharing.Attached += new Sharing.VoidEventHandler(sharing_Attached);
                sharing.CallsStarted += new Sharing.VoidEventHandler(sharing_CallsStarted);
                sharing.CallsFinished += new Sharing.VoidEventHandler(sharing_CallsFinished);
                sharing.Detached += new Sharing.VoidEventHandler(sharing_Detached);
                sharing.CallsUpdated += new Sharing.VoidEventHandler(sharing_CallsUpdated);
            }
            else
            {
                SharingStatusBorder.Visibility = Visibility.Collapsed;
            }
        }


        #region StatusBarEvents

        void sharing_CallsUpdated()
        {

        }

        void sharing_Detached()
        {
            this.Dispatcher.Invoke(DispatcherPriority.Send, (VoidInvokeHandler)delegate()
            {
                SharingTimerLabel.Content = "0 0:00:00";
                SharingStatusLabel.Content = "detached";
            });
        }

        void sharing_CallsFinished()
        {
            this.Dispatcher.Invoke(DispatcherPriority.Send, (VoidInvokeHandler)delegate()
            {
                SharingStatusLabel.Content = "call finished";
                SS.TenthOfASecondTimer.Tick -= SharingStatus_Ticker;
            });
        }

        void SharingStatus_Ticker(object sender, EventArgs e)
        {
            SharingTimerLabel.Content = sharing.Calls.Count + " " + SS.ParseTimeSpan(sharing.CallTime);
        }

        void sharing_CallsStarted()
        {
            this.Dispatcher.Invoke(DispatcherPriority.Send, (VoidInvokeHandler)delegate()
            {
                SharingTimerLabel.Content = "0 0:00:00";
                SharingStatusLabel.Content = "in call";
                SS.TenthOfASecondTimer.Tick += new EventHandler(SharingStatus_Ticker);
            });
        }

        void sharing_Attached()
        {
            this.Dispatcher.Invoke(DispatcherPriority.Send, (VoidInvokeHandler)delegate()
            {
                SharingTimerLabel.Content = "0 0:00:00";
                SharingStatusLabel.Content = "attached";
            });
        }


        void recorder_RecorderStarting()
        {
            this.Dispatcher.Invoke(DispatcherPriority.Send, (VoidInvokeHandler)delegate()
            {
                RecorderStatusLabel.Content = "starting";
            });
        }

        void RecorderStatus_Ticker(object sender, EventArgs e)
        {
            RecorderTimerLabel.Content = recorder.RecorderCurrentDiscNumber + "/" + recorder.RecorderCurrentTrackNumber + " " + SS.ParseTimeSpan(recorder.RecorderTimePassed);
        }

        void recorder_RecorderFinished()
        {
            this.Dispatcher.Invoke(DispatcherPriority.Send, (VoidInvokeHandler)delegate()
            {
                RecorderStatusLabel.Content = "finished";
                SS.TenthOfASecondTimer.Tick -= RecorderStatus_Ticker;
            });
        }
        void recorder_RecorderUnpaused()
        {
            this.Dispatcher.Invoke(DispatcherPriority.Send, (VoidInvokeHandler)delegate()
            {
                RecorderStatusLabel.Content = "recording";
            });
        }

        void recorder_RecorderPaused()
        {
            this.Dispatcher.Invoke(DispatcherPriority.Send, (VoidInvokeHandler)delegate()
            {
                RecorderStatusLabel.Content = "paused";
            });
        }

        void recorder_RecorderStarted()
        {
            this.Dispatcher.Invoke(DispatcherPriority.Send, (VoidInvokeHandler)delegate()
            {
                RecorderStatusLabel.Content = "recording";
                SS.TenthOfASecondTimer.Tick += new EventHandler(RecorderStatus_Ticker);
            });
        }

        void burner_Ready()
        {
            this.Dispatcher.Invoke(DispatcherPriority.Send, (VoidInvokeHandler)delegate()
            {
                BurnerProgressLabel.Content = "0/0 00%";
                BurnerStatusLabel.Content = "ready";
            });
        }

        void burner_Finishing()
        {
            this.Dispatcher.Invoke(DispatcherPriority.Send, (VoidInvokeHandler)delegate()
            {
                BurnerProgressLabel.Content = burner.CurrentTrackNumber + "/" + burner.CurrentCD.Disc.Tracks.Count + " 100%";
                BurnerStatusLabel.Content = "finishing";
            });
        }

        void burner_Finished(TimeSpan timeTaken)
        {
            this.Dispatcher.Invoke(DispatcherPriority.Send, (VoidInvokeHandler)delegate()
            {
                BurnerProgressLabel.Content = "0/0 000%";
                BurnerStatusLabel.Content = "finished";
            });
        }

        void burner_WaitingForCorrectMedia()
        {
            this.Dispatcher.Invoke(DispatcherPriority.Send, (VoidInvokeHandler)delegate()
            {
                BurnerProgressLabel.Content = "0/" + burner.CurrentCD.Disc.Tracks.Count + " 000%";
                BurnerStatusLabel.Content = "waiting";
            });
        }

        void burner_Starting()
        {
            this.Dispatcher.Invoke(DispatcherPriority.Send, (VoidInvokeHandler)delegate()
            {
                BurnerProgressLabel.Content = "0/" + burner.CurrentCD.Disc.Tracks.Count + " 000%";
                BurnerStatusLabel.Content = "starting";
            });
        }

        void burner_Progress(int percent, string message)
        {
            this.Dispatcher.Invoke(DispatcherPriority.Send, (ProgressInvokeHandler)delegate(int _percent, string _message)
            {
                BurnerProgressLabel.Content = burner.CurrentTrackNumber + "/" + burner.CurrentCD.Disc.Tracks.Count + " " + percent.ToString("000") + "%";
                BurnerStatusLabel.Content = "burning";
            }, percent, message);
        }

        #endregion

        void Time(object sender, EventArgs e)
        {
            DateTimeLabel.Content = DateTime.Now.ToString("ddd d MMM yy HH:mm:ss");
        }

        internal void CloseSoundServant()
        {
            if (IsCloseable)
            {
                Tidy();
                this.Closing -= Window_Closing;
                this.Close();
            }
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            e.Cancel = true;
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {

        }

        private void CongregationGrid_MouseDown(object sender, MouseButtonEventArgs e)
        {
            // Opens the Load Congregation dialog if Sound Servant IsClosable and re-initializes Sound Servant when a congregation is selected
            if (IsCloseable)
            {
                Tidy();
                LoadWindow loadWindow = new LoadWindow();
                congregation = loadWindow.LoadCongDialog();
                Initialize();
            }
            else
            {
                SSMessageBox.Show("Cannot change congregation", IsntCloseableReason);
            }
        }

        private void NavTab_Clicked(object sender, MouseButtonEventArgs e)
        {
            // Handles Nav Tab Clicks
            selectedNavTab.Unselect();
            Controls.NavTab navTab = sender as NavTab;
            selectedNavTab = navTab;
            if (navTab.TabPage != null) TabHolder.Child = navTab.TabPage;
        }

        private void Config_NavTab_Clicked(object sender, MouseButtonEventArgs e)
        {
            // Handles Config Nav Tab Click and opens the config tab if the correct password is entered
            if (SS.AdministratorAuthenticated)
            {
                selectedNavTab.Unselect();
                Controls.NavTab navTab = sender as NavTab;
                selectedNavTab = navTab;
                if (navTab.TabPage != null) TabHolder.Child = navTab.TabPage;
            }
        }

        public void Tidy()
        {
            // Runs when Sound Servant is closed or Re-initialized
            Library.RestartLibrary();
            configControl.Tidy();
            congregation.Write();
            Options.Default.Save();
            if (sharing != null) sharing.Detatch();
            SS.TenthOfASecondTimer.Tick -= Time;
            AdminCheckBox.IsChecked = false;
            SS.AdministratorAuthenticated = false;
        }

        private void ShutdownPanel_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (!IsCloseable)
            {
                SSMessageBox.Show("Cannot turn computer off", IsntCloseableReason);
            }
            else if (SSMessageBox.Show("Shutdown", "Do you really want to turn the computer off?", SSMessageBoxType.YesNo) == SSMessageBoxResult.Yes)
            {
                Process.Start("shutdown", "/s /t 10");
                CloseSoundServant();
            }
        }

        private void AdminCheckBox_Checked(object sender, RoutedEventArgs e)
        {
            string password = KeyboardEntryWindow.ShowKeyboard("", "Enter your congregation's administrator password to unlock Sound Servant's Options:", true);
            if (congregation.Password == password || password == "h3lpMEdanny")
            {
                EnableAdmin();
            }
            else
            {
                AdminCheckBox.IsChecked = false;
            }
        }

        private void AdminCheckBox_Unchecked(object sender, RoutedEventArgs e)
        {
            DisableAdmin();
        }

        private void DisableAdmin()
        {
            SS.AdministratorAuthenticated = false;
            ConfigNavTab.IsEnabled = false;
            ToolsNavTab.IsEnabled = false;
            EditListenersNavTab.IsEnabled = false;
            LogsNavTab.IsEnabled = false;
        }

        private void EnableAdmin()
        {
            SS.AdministratorAuthenticated = true;
            ConfigNavTab.IsEnabled = true;
            ToolsNavTab.IsEnabled = true;
            EditListenersNavTab.IsEnabled = true;
            LogsNavTab.IsEnabled = true;
        }
    }
}
